﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace SysSU.JSONRPC
{
    public abstract class JSONRPC2Message 
    {
        public static JSONRPC2Message Parse(string jsonString)
        {
            try
            {
                var jsonObject = JObject.Parse(jsonString);
            }
            catch (Exception ex)
            {
                throw new JSONRPC2ParseException("Invalid JSON: " + ex.Message, jsonString);
            }

            //try { return JSONRPC2Request.Parse(jsonString); } catch (Exception e) {}
            //try { return JSONRPC2Notification.Parse(jsonString); } catch (Exception e) {}
            try { return JSONRPC2Response.Parse(jsonString); } catch {}
            //try { return JSONRPC2Subscription.Parse(jsonString); } catch (Exception e) {}

            throw new JSONRPC2InvalidMessageException("Invalid JSON-RPC 2.0 message", jsonString);
        }

        protected static Dictionary<string, object> ParseJSONObject(string jsonString)
        {
            if (jsonString == null) 
            {
                throw new JSONRPC2ParseException("Null argument");
            }

            if (jsonString.Trim().Length == 0) 
            {
                throw new JSONRPC2ParseException("Invalid JSON: Empty string");
            }

            try
            {
                return JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
            }
            catch (Exception ex)
            {
                throw new JSONRPC2ParseException("Invalid JSON: " + ex.Message, jsonString);
            }
        }

        protected static void ensureVersion2(Object version, String jsonString)
        {
            if (version == null) 
            {
                throw new JSONRPC2InvalidMessageException(
                        "Invalid JSON-RPC 2.0: Version string missing", jsonString);
            } 
            else if (!(version is String))
            {
                throw new JSONRPC2InvalidMessageException(
                        "Invalid JSON-RPC 2.0: Version not a JSON string", jsonString);
            } 
            else if (!version.Equals("2.0")) 
            {
                throw new JSONRPC2InvalidMessageException(
                        "Invalid JSON-RPC 2.0: Version must be \"2.0\"", jsonString);
            }
        }

        protected static void verifyType(Object value)
        {
            if (value != null && !(value is bool)
                                && !(value is byte) && !(value is sbyte)
                                && !(value is short) && !(value is ushort)
                                && !(value is int) && !(value is uint)
                                && !(value is long) && !(value is ulong)
                                && !(value is float) && !(value is double)
                                && !(value is String))
            {
                throw new ArgumentException("The request identifier must map to a JSON scalar");
            }
        }

        public abstract JObject ToJSON();

        public override string ToString()
        {
            return ToJSON().ToString();
        }    
    }
}
